
import Cesium from '../Ces/Cesium'
import Util from '../Core/Util'
import FluidMesh from './FluidMesh'
import FluidNeighbor from './FluidNeighbor'
import FluidParameter from './FluidParameter'
import FluidUniform from './FluidUniform'
import FluidWater from './FluidWater'

class FluidPrimitive {
  primitive: FluidMesh
  fluidWater: FluidWater
  terrainImage
  terrainTexture:any// Cesium.Textrue
  currentWater: any//Cesium.Texture
  lastWater: any//Cesium.Texture
  flows: any//Cesium.Texture
  tmp: any//Cesium.Texture
  fluidNeighbor: FluidNeighbor = new FluidNeighbor()
  fluidUniform: FluidUniform
  fluidParameter: FluidParameter
  constructor({
    terrainImage,
    fluidParameter,
  }) {
    this.terrainImage = terrainImage
    this.fluidParameter = fluidParameter
    this.fluidUniform = new FluidUniform(terrainImage)
  }

  update(frameState) {
    if (!frameState.passes.render) return
    if (this.terrainImage) {
      const context = frameState.context
      const terrainTexture = new Cesium.Texture({
        context,
        pixelFormat: this.terrainImage.source.pixelFormat,
        pixelDatatype: this.terrainImage.source.pixelDatatype || this.terrainImage.source.pixelType,
        source: this.terrainImage.source,
        sampler: new Cesium.Sampler({
          minificationFilter: Cesium.TextureMinificationFilter.NEAREST,
          magnificationFilter: Cesium.TextureMagnificationFilter.NEAREST,
        })
      })

      const currentWater = new Cesium.Texture({
        context,
        pixelFormat: Cesium.PixelFormat.RGBA,
        pixelDatatype: Cesium.PixelDatatype.FLOAT,
        width: terrainTexture.width,
        height: terrainTexture.height,
        // sampler: new Cesium.Sampler({
        //   minificationFilter: Cesium.TextureMinificationFilter.NEAREST,
        //   magnificationFilter: Cesium.TextureMagnificationFilter.NEAREST,
        // })
      })

      const lastWater = new Cesium.Texture({
        context,
        pixelFormat: Cesium.PixelFormat.RGBA,
        pixelDatatype: Cesium.PixelDatatype.FLOAT,
        width: terrainTexture.width,
        height: terrainTexture.height,
        sampler: new Cesium.Sampler({
          minificationFilter: Cesium.TextureMinificationFilter.NEAREST,
          magnificationFilter: Cesium.TextureMagnificationFilter.NEAREST,
        })
      })

      const flows = new Cesium.Texture({
        context,
        pixelFormat: Cesium.PixelFormat.RGBA,
        pixelDatatype: Cesium.PixelDatatype.FLOAT,
        width: terrainTexture.width / 1,
        height: terrainTexture.height / 1,
        sampler: new Cesium.Sampler({
          minificationFilter: Cesium.TextureMinificationFilter.NEAREST,
          magnificationFilter: Cesium.TextureMagnificationFilter.NEAREST,
        })
      })

      const tmp = new Cesium.Texture({
        context,
        pixelFormat: Cesium.PixelFormat.RGBA,
        pixelDatatype: Cesium.PixelDatatype.FLOAT,
        width: terrainTexture.width,
        height: terrainTexture.height,
        sampler: new Cesium.Sampler({
          minificationFilter: Cesium.TextureMinificationFilter.NEAREST,
          magnificationFilter: Cesium.TextureMagnificationFilter.NEAREST,
        })
      })

      Util.setRefDestroy(terrainTexture, 1, () => {
        // console.log('ref destroy.')
      })
      Util.setRefDestroy(currentWater, 1)
      Util.setRefDestroy(lastWater, 1,)
      Util.setRefDestroy(tmp, 1,)

      const fluidParameter = this.fluidParameter
      const fluidNeighbor = this.fluidNeighbor
      const fluidUniform = this.fluidUniform

      const options = {
        terrainTexture,
        currentWater,
        lastWater,
        fluidParameter,
        fluidNeighbor,
        fluidUniform,
        flows,
        tmp,
      }

      this.fluidNeighbor.defaultTexture = context.defaultTexture
      this.fluidWater = new FluidWater(options, context)
      this.primitive = new FluidMesh({
        ...options,
      }, context)

      this.terrainImage = null
      this.terrainTexture = terrainTexture
      this.currentWater = currentWater
      this.lastWater = lastWater
      this.flows = flows
      this.tmp = tmp
    }

    this.fluidWater.update(frameState)
    this.primitive.update(frameState)
  }

  destroy() {
    this.primitive = this.primitive && this.primitive.destroy()
    this.fluidWater = this.fluidWater && this.fluidWater.destroy()
    this.fluidNeighbor = this.fluidNeighbor && this.fluidNeighbor.destroy()
    this.terrainTexture = this.terrainTexture && this.terrainTexture.destroy()
    this.currentWater = this.currentWater && this.currentWater.destroy()
    this.lastWater = this.lastWater && this.lastWater.destroy()
    this.flows = this.flows && this.flows.destroy()
    this.tmp = this.tmp && this.tmp.destroy()

    return Cesium.destroyObject(this)
  }

  isDestroyed() {
    return false
  }
}

export default FluidPrimitive
